package org.framework.common.api.service.bo;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.framework.common.api.entity.CommonEntityAware;
import org.framework.common.api.service.dao.CommonDaoAware;
import org.framework.common.api.support.model.ChosenModel;
import org.framework.common.api.support.model.FormModel;
import org.framework.common.api.support.model.PageModel;
import org.framework.common.api.support.model.QueryModel;
import org.framework.common.api.support.model.TreeModel;
import org.framework.common.ext.util.ClassUtil;
import org.framework.common.ext.util.StringUtil;
import org.hibernate.jpa.internal.util.PersistenceUtilHelper;
import org.springframework.stereotype.Service;
import org.springframework.ui.ModelMap;

@Service("defaultBo")
public class CommonBoDefault<ENTITY extends CommonEntityAware<ID>, ID extends Serializable> extends CommonBoAdapter<ENTITY, ID> {

	@Resource(name = "defaultDao")
	protected CommonDaoAware<ENTITY, ID> dao;
	
	/**
	 * 新增
	 * @see ces.framework.common.web.dbo.CommonBoAdapter#insert(ces.framework.common.entity.CommonEntity)
	 * @author chanlong(陈龙)
	 * @date 2013年12月23日 下午4:15:36
	 */
	@Override
	public ENTITY insert(final ENTITY entity) throws Exception {
		return dao.insert(entity);
	}

	/**
	 * 批量新增
	 * @see ces.framework.common.web.dbo.CommonBoAdapter#insertAll(java.util.List)
	 * @author chanlong(陈龙)
	 * @date 2013年12月23日 下午4:15:36
	 */
	@Override
	public List<ENTITY> insertAll(final List<ENTITY> entities) throws Exception {
		for (ENTITY entity : entities) {
			this.insert(entity);
		}
		return entities;
	}
	
	/**
	 * 更新
	 * @see ces.framework.common.web.dbo.CommonBoAdapter#update(ces.framework.common.entity.CommonEntity)
	 * @author chanlong(陈龙)
	 * @date 2013年12月28日 下午1:37:32
	 */
	@Override
	public ENTITY update(final ENTITY entity) throws Exception {
		if(StringUtil.isEmpty(entity.getId()) && (params == null || params.isEmpty())){
			entity.setId(null);
			return dao.insert(entity);
		}else{
			try{
				switch(PersistenceUtilHelper.isLoaded(entity)){
					case LOADED: return dao.update(entity);
					default:{
						ENTITY dest = (params == null || params.isEmpty()) ? this.loader(entity) : dao.loader(ClassUtil.getClass(entity), params);
						if(dest == null){
							return dao.insert(entity);
						}else{
							ClassUtil.copyProperties(entity, dest);
							return dao.update(dest);
						}
					}
				}
			}finally{
				clearParams();
			}
		}
	}
	
	/**
	 * @see org.framework.common.api.service.bo.CommonBoAdapter#update(org.framework.common.api.entity.CommonEntityAware, java.lang.String, java.lang.Object)
	 * @author chanlong(陈龙)
	 * @date 2016年4月9日 下午6:29:02
	 */
	@Override
	public void update(final ENTITY entity, final String field, final Object value) throws Exception{
		ENTITY dest = dao.loader(ClassUtil.getClass(entity), field, value);
		ClassUtil.copyProperties(entity, dest);
		this.update(dest);
	}

	/**
	 * 批量更新
	 * @see ces.framework.common.web.dbo.CommonBoAdapter#updateAll(java.util.List)
	 * @author chanlong(陈龙)
	 * @date 2013年12月28日 下午1:37:32
	 */
	@Override
	public void updateAll(final List<ENTITY> entities) throws Exception {
		for (ENTITY entity : entities) {
			this.update(entity);
		}
	}

	/**
	 * 根据对象删除实体
	 * 对象中应至少包含主键信息
	 * @see ces.framework.common.web.dbo.CommonBoAdapter#delete(ces.framework.common.entity.CommonEntity)
	 * @author chanlong(陈龙)
	 * @date 2014年8月3日 下午1:01:02
	 */
	@Override
	public void delete(ENTITY entity) throws Exception {
		dao.remove(this.loader(entity));
	}

	/**
	 * 根据主键删除实体
	 * @see ces.framework.common.web.dbo.CommonBoAdapter#delete(java.io.Serializable)
	 * @author chanlong(陈龙)
	 * @date 2013年12月28日 下午1:37:32
	 */
	@Override
	public void delete(final Class<ENTITY> cls, final ID id) throws Exception {
		dao.remove(this.loader(cls, id));
	}

	/**
	 * 批量删除
	 * @see ces.framework.common.web.dbo.CommonBoAdapter#deleteAll(java.io.Serializable[])
	 * @author chanlong(陈龙)
	 * @date 2013年12月28日 下午1:37:32
	 */
	@Override
	@SuppressWarnings("unchecked")
	public void deleteAll(final Class<ENTITY> cls, final ID... ids) throws Exception {
		for (ID id : ids) {
			this.delete(cls, id);
		}
	}
	
	/**
	 * 根据对象查询实体
	 * 对象中应至少包含主键信息
	 * @see ces.framework.common.web.dbo.CommonBoAdapter#loader(ces.framework.common.entity.CommonEntity)
	 * @author Administrator(陈龙)
	 * @date 2014-1-22 下午2:07:43
	 */
	@Override
	public ENTITY loader(final ENTITY entity) throws Exception {
		return dao.loader(entity);
	}

	/**
	 * 根据主键查询实体
	 * @see ces.framework.common.web.dbo.CommonBoAdapter#loader(java.lang.Class, java.io.Serializable)
	 * @author chanlong(陈龙)
	 * @date 2013年12月28日 下午1:56:05
	 */
	@Override
	public ENTITY loader(final Class<ENTITY> cls, final ID id) throws Exception {
		return dao.loader(cls, id);
	}
	
	/**
	 * 根据字段查询实体
	 * @see org.framework.common.api.service.bo.CommonBoAware#loader(java.lang.Class, java.util.Map)
	 * @author chanlong(陈龙)
	 * @date 2016年8月30日 上午11:47:42
	 */
	@Override
	public ENTITY loader(final Class<ENTITY> cls, final Map<String,Object> params) throws Exception {
		return dao.loader(cls, params);
	}
	
	/**
	 * 根据字段查询实体
	 * @see ces.framework.common.web.dbo.CommonBoAdapter#loader(java.lang.Class, java.lang.String, java.lang.Object)
	 * @author chanlong(陈龙)
	 * @date 2014年4月25日 下午9:22:03
	 */
	@Override
	public ENTITY loader(final Class<ENTITY> cls, final String field, final Object value) throws Exception {
		return dao.loader(cls, field, value);
	}
	
	/**
	 * 根据主键查询实体集合
	 * @see ces.framework.common.web.dbo.CommonBoAdapter#findByIds(java.lang.Class, java.lang.String[])
	 * @author chanlong(陈龙)
	 * @date 2014年3月3日 上午10:43:25
	 */
	@Override
	@SuppressWarnings("unchecked")
	public List<ENTITY> findByIds(final Class<ENTITY> cls, final ID... ids) throws Exception {
		List<ENTITY> entitys = new ArrayList<ENTITY>();
		for (ID id : ids) {
			entitys.add(this.loader(cls, id));
		}
		return entitys;
	}

	/**
	 * 结果数
	 * @see org.framework.common.api.service.bo.CommonBoAdapter#count(org.framework.common.api.support.model.QueryModel)
	 * @author chanlong(陈龙)
	 * @date 2016年4月13日 下午3:17:47
	 */
	@Override
	public long count(final QueryModel model) throws Exception {
		return dao.count(model);
	}
	
	/**
	 * 分页条件查询
	 * @see org.framework.common.api.service.bo.CommonBoAdapter#findByQuery(org.framework.common.api.support.model.QueryModel)
	 * @author chanlong(陈龙)
	 * @date 2016年1月20日 下午1:11:34
	 */
	@Override
	public PageModel<ENTITY> findByQuery(final QueryModel model) throws Exception {
		return dao.findByQuery(model);
	}
	
	/**
	 * 下拉组件
	 * @see org.framework.common.api.service.bo.CommonBoAdapter#select(org.framework.common.api.support.model.FormModel)
	 * @author chanlong(陈龙)
	 * @date 2016年1月30日 上午10:17:03
	 */
	@Override
	public ChosenModel[] select(final FormModel model) throws Exception{
		List<ENTITY> result = result(model);
		return ChosenModel.create(result);
	}
	
	/**
	 * 数组件.
	 * @param model
	 * @return
	 * @throws Exception
	 * @author chanlong(陈龙)
	 * @date 2016年3月30日 上午10:54:40
	 */
	@Override
	public TreeModel[] tree(final QueryModel model) throws Exception{
		List<?> result = dao.findByQuery(model).getRows();
		return TreeModel.create(result);
	}
	
	/*
	 * 返回查询结果
	 */
	private List<ENTITY> result(final FormModel model) throws Exception{
		Class<ENTITY> entityClass = model.getEntityClass();
		String entityName = model.getEntityName();
		ModelMap bean = model.getBean();
		
		return dao.findByQuery(entityClass, this.from(entityName).where(bean), bean);
	}
}
